.\" Copyright (c) 2002-2020 Julien Nadeau Carriere <vedge@csoft.net>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\"    notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\"    notice, this list of conditions and the following disclaimer in the
.\"    documentation and/or other materials provided with the distribution.
.\" 
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
.\" (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd August 21, 2002
.Dt AG_TEXTBOX 3
.Os
.ds vT Agar API Reference
.ds oS Agar 1.0
.Sh NAME
.Nm AG_Textbox
.Nd agar text editor widget
.Sh SYNOPSIS
.Bd -literal
#include <agar/core.h>
#include <agar/gui.h>
.Ed
.Sh DESCRIPTION
.\" IMAGE(http://libagar.org/widgets/AG_Textbox.png, "A single-line AG_Textbox(3) widget")
The
.Nm
widget implements text edition.
.Nm
may be bound to a fixed-size buffer containing a "C" string (a NUL-terminated string)
or a dynamically-sized
.Xr AG_TextElement 3 .
.Pp
.\" IMAGE(http://libagar.org/widgets/AG_TextboxMulti.png, "A multi-line AG_Textbox(3) widget")
The string bound to
.Nm
may use different encodings (support for US-ASCII, UTF-8 and UCS-4 is built-in,
conversion to/from other encodings requires that Agar be built with
.Xr iconv 3
support).
.Pp
Most of the functionality of
.Nm
is actually implemented in
.Xr AG_Editable 3 .
The
.Nm
widget itself only acts as a container for an
.Ft AG_Editable
(adding an optional text label, scrollbars and buttons).
Direct buffer-access routines are available in
.Xr AG_Editable 3 .
.Sh INHERITANCE HIERARCHY
.Xr AG_Object 3 ->
.Xr AG_Widget 3 ->
.Nm .
.Sh INITIALIZATION
.nr nS 1
.Ft "AG_Textbox *"
.Fn AG_TextboxNew "AG_Widget *parent" "Uint flags" "const char *format" "..."
.Pp
.Ft "AG_Textbox *"
.Fn AG_TextboxNewS "AG_Widget *parent" "Uint flags" "const char *label"
.Pp
.Ft "void"
.Fn AG_TextboxBindUTF8 "AG_Textbox *textbox" "char *buffer" "AG_Size size"
.Pp
.Ft "void"
.Fn AG_TextboxBindASCII "AG_Textbox *textbox" "char *buffer" "AG_Size size"
.Pp
.Ft "void"
.Fn AG_TextboxBindEncoded "AG_Textbox *textbox" "const char *encoding" "char *buffer" "AG_Size size"
.Pp
.Ft "void"
.Fn AG_TextboxBindText "AG_Textbox *textbox" "AG_Text *txt"
.Pp
.Ft void
.Fn AG_TextboxSetLang "AG_Textbox *textbox" "enum ag_language lang"
.Pp
.Ft void
.Fn AG_TextboxSetExcl "AG_Textbox *textbox" "int enable"
.Pp
.Ft void
.Fn AG_TextboxSetPassword "AG_Textbox *textbox" "int enable"
.Pp
.Ft void
.Fn AG_TextboxSetWordWrap "AG_Textbox *textbox" "int enable"
.Pp
.Ft void
.Fn AG_TextboxSetIntOnly "AG_Textbox *textbox" "int enable"
.Pp
.Ft void
.Fn AG_TextboxSetFltOnly "AG_Textbox *textbox" "int enable"
.Pp
.Ft void
.Fn AG_TextboxSetLabel "AG_Textbox *textbox" "const char *format" "..."
.Pp
.Ft void
.Fn AG_TextboxSetLabelS "AG_Textbox *textbox" "const char *label"
.Pp
.Ft void
.Fn AG_TextboxSetPlaceholder "AG_Textbox *textbox" "const char *fmt" "..."
.Pp
.Ft void
.Fn AG_TextboxSetPlaceholderS "AG_Textbox *textbox" "const char *s"
.Pp
.Ft void
.Fn AG_TextboxSizeHint "AG_Textbox *textbox" "const char *text"
.Pp
.Ft void
.Fn AG_TextboxSizeHintPixels "AG_Textbox *textbox" "Uint w" "Uint h"
.Pp
.Ft void
.Fn AG_TextboxSizeHintLines "AG_Textbox *textbox" "Uint nLines"
.Pp
.Ft void
.Fn AG_TextboxAutocomplete "AG_Textbox *tb" "void (*fn)(AG_Event *)" "const char *fnArgs" "..."
.Pp
.nr nS 0
The
.Fn AG_TextboxNew
function allocates, initializes, and attaches a new
.Nm
widget.
The optional string argument specifies a text label to display at the left
of the textbox.
Acceptable
.Fa flags
include:
.Bl -tag -width "AG_TEXTBOX_ABANDON_FOCUS "
.It AG_TEXTBOX_MULTILINE
Causes newlines to be entered literally into the string, and arranges for
horizontal and vertical scrollbars to appear if the text is larger than the
display area.
.It AG_TEXTBOX_WORDWRAP
Enable word wrapping in multiline mode.
.It AG_TEXTBOX_MULTILINGUAL
Allow the user to select different languages from the right-click popup
menu (provided the widget is bound to an
.Xr AG_TextElement 3 ) .
.It AG_TEXTBOX_RETURN_BUTTON
Display a RETURN button which generates "textbox-return" when clicked.
.It AG_TEXTBOX_EXCL
By default, external changes to the contents of the buffer are allowed and
handled in a safe manner (at the cost of frequent character set conversions
and periodical redrawing of the widget).
If
.Dv AG_TEXTBOX_EXCL
is set,
.Nm
will assume exclusive access to the buffer, permitting some important
optimizations (i.e., periodic redrawing and character set conversions
are avoided).
.It AG_TEXTBOX_UPPERCASE
Display all characters in upper-case.
.It AG_TEXTBOX_LOWERCASE
Display all characters in lower-case.
.It AG_TEXTBOX_PASSWORD
Password-style entry where characters are hidden.
.Fn AG_TextboxSetPassword
sets this flag.
.It AG_TEXTBOX_ABANDON_FOCUS
Arrange for the widget to abandon its focus when the return key is pressed.
.It AG_TEXTBOX_INT_ONLY
Restricts input to valid integers only.
Use
.Fn AG_TextboxSetIntOnly
to change at runtime.
.It AG_TEXTBOX_FLT_ONLY
Restricts input to valid floating-point numbers in decimal and scientific
notation ("inf" and the Unicode symbol for Infinity may also be used).
Use
.Fn AG_TextboxSetFltOnly
to change at runtime.
.It AG_TEXTBOX_CATCH_TAB
Cause tabs to be entered literally into the string (by default, the tab
key moves focus to the next widget).
.It AG_TEXTBOX_NO_KILL_YANK
Disable Kill (ctrl-K) and Yank (ctrl-Y) functions.
.It AG_TEXTBOX_NO_ALT_LATIN1
Disable alt-key mappings to extended Latin1 characters.
.It AG_TEXTBOX_NOPOPUP
Disable the standard right-click popup menu.
.It AG_TEXTBOX_READONLY
Make the string read-only.
This has the same effect as using
.Xr AG_WidgetDisable 3 ,
except that the textbox is not grayed out.
.It AG_TEXTBOX_NO_SHADING
Disable 3D-style shading around the field.
.It AG_TEXTBOX_HFILL
Expand horizontally in parent container.
.It AG_TEXTBOX_VFILL
Expand vertically in parent container.
.It AG_TEXTBOX_EXPAND
Shorthand for
.Dv AG_TEXTBOX_HFILL | AG_TEXTBOX_VFILL .
.El
.Pp
.Fn AG_TextboxBindUTF8
and
.Fn AG_TextboxBindASCII
connect a textbox to a buffer containing Unicode or US-ASCII, respectively.
.Fa size
is the size of the buffer in bytes (which must include space for
the terminating NUL).
.Pp
.Fn AG_TextboxBindEncoded
binds to a fixed-size buffer containing a C string in the specified
encoding.
Support for the "US-ASCII" and "UTF-8" encodings is built-in, but
conversion to other encodings requires that Agar be compiled with
.Xr iconv 3
support (see
.Xr iconv_open 3
for the complete list of supported encodings).
.Pp
.Fn AG_EditableBindText
connects the
.Nm
to a
.Xr AG_TextElement 3
object, which can represent text in different languages.
.Pp
The
.Fn AG_EditableSetLang
function selects the specified language for the current
.Xr AG_TextElement 3 .
.Pp
The
.Fn AG_TextboxSetExcl
function sets exclusive access to the buffer.
Enable only if the bound string is guaranteed not to change externally (see
.Dv AG_TEXTBOX_EXCL
flag description above).
.Pp
The
.Fn AG_TextboxSetPassword
function enables/disables password-type input, where characters are substituted
for
.Sq *
in the display.
.Pp
.Fn AG_TextboxSetWordWrap
enables/disable word wrapping.
.Pp
.Fn AG_TextboxSetIntOnly
restricts input to integers (see flags)
.Fn AG_TextboxSetFltOnly
restricts input to real numbers (see flags).
.Pp
.Fn AG_TextboxSetLabel
changes the current label text to the specified string.
.Pp
.Fn AG_TextboxSetPlaceholder
sets the "place holder" text to display when the buffer is empty.
An argument of NULL disables placeholder text.
.Pp
.Fn AG_TextboxSizeHint
requests that the initial geometry of
.Fa textbox
is to be sufficient to display the string
.Fa text
in its entirety.
The
.Fn AG_TextboxSizeHintPixels
variant accepts arguments in pixels.
.Fn AG_TextboxSizeHintLines
accepts a number of lines.
.Pp
.Fn AG_TextboxAutocomplete
sets up an autocomplete routine
.Fa fn ,
which will be passed a pointer to an
.Xr AG_Tlist 3
as first argument (and a pointer to the
.Xr AG_Editable 3
instance as SELF).
The autocomplete routine is expected to populate the tlist with
suggestions based on the current buffer contents.
If the
.Fa fn
argument is NULL, disable autocomplete (closing any active windows).
If an autocomplete context has already been configured, only its function
and arguments are updated (and any active timers are cancelled).
If non-NULL,
.Fa fnArgs
indicates additional
.Xr AG_Event 3
style arguments to be passed to the autocomplete routine.
.Sh CURSOR MANIPULATION
.nr nS 1
.Ft int
.Fn AG_TextboxMapPosition "AG_Textbox *textbox" "int x" "int y" "int *pos"
.Pp
.Ft void
.Fn AG_TextboxMoveCursor "AG_Textbox *textbox" "int x" "int y"
.Pp
.Ft int
.Fn AG_TextboxGetCursorPos "AG_Textbox *textbox"
.Pp
.Ft int
.Fn AG_TextboxSetCursorPos "AG_Textbox *textbox" "int pos"
.Pp
.nr nS 0
The
.Fn AG_TextboxMapPosition
function translates pixel coordinates
.Fa x
and
.Fa y
to a character position within the text buffer.
On success, the position is returned into
.Fa pos .
The function returns 0 on success or -1 on failure.
.Pp
.Fn AG_TextboxMoveCursor
moves the text cursor to the position closest to the pixel coordinates
.Fa mx
and
.Fa my .
.Pp
.Fn AG_TextboxGetCursorPos
returns the current position of the cursor in the buffer.
The return value is only valid as long as the widget remains locked.
.Pp
.Fn AG_TextboxSetCursorPos
tries to move the cursor to the specified position in the string, after
bounds checking is done.
If
.Fa pos
is -1, the cursor is moved to the end of the string.
.Fn AG_TextboxSetCursorPos
returns the new position of the cursor.
.Sh TEXT MANIPULATION
.nr nS 1
.Ft void
.Fn AG_TextboxPrintf "AG_Textbox *textbox" "const char *fmt" "..."
.Pp
.Ft void
.Fn AG_TextboxSetString "AG_Textbox *textbox" "const char *s"
.Pp
.Ft void
.Fn AG_TextboxClearString "AG_Textbox *textbox"
.Pp
.Ft "char *"
.Fn AG_TextboxDupString "AG_Textbox *textbox"
.Pp
.Ft "AG_Size"
.Fn AG_TextboxCopyString "AG_Textbox *textbox" "char *dst" "AG_Size dst_size"
.Pp
.Ft "void"
.Fn AG_TextboxBufferChanged "AG_Textbox *textbox"
.Pp
.Ft int
.Fn AG_TextboxInt "AG_Textbox *textbox"
.Pp
.Ft float
.Fn AG_TextboxFlt "AG_Textbox *textbox"
.Pp
.Ft double
.Fn AG_TextboxDbl "AG_Textbox *textbox"
.Pp
.nr nS 0
The
.Fn AG_TextboxPrintf
function uses
.Xr vsnprintf 3
to overwrite the contents of the buffer.
If the
.Fa fmt
argument is NULL, a NUL string is assigned instead.
.Pp
.Fn AG_TextboxSetString
overwrites the contents of the buffer with the given string.
The argument may be NULL to clear the string.
.Pp
.Fn AG_TextboxClearString
clears the contents of the buffer.
.Pp
The
.Fn AG_TextboxDupString
function returns a copy of the text buffer, as-is.
.Fn AG_TextboxCopyString
copies the contents of the text buffer to a fixed-size buffer
(up to
.Fa dst_size
- 1 bytes will be copied).
Returns the number of bytes that would have been copied were
.Fa dst_size
unlimited (i.e., if the return value is >=
.Fa dst_size ,
truncation has occurred).
Both
.Fn AG_TextboxDupString
and
.Fn AG_TextboxCopyString
return the raw contents of the text buffer, without performing
any character set conversion.
.Pp
The
.Fn AG_TextboxBufferChanged
function signals an outside change in the buffer contents.
It is only useful if the
.Nm AG_TEXTBOX_STATIC
flag is set.
.Pp
.Fn AG_TextboxInt ,
.Fn AG_TextboxFlt
and
.Fn AG_TextboxDbl
perform conversion of the string contents to
.Ft int
.Ft float
and
.Ft double ,
respectively and return the value.
You probably want to be using the
.Xr AG_Numerical 3
widget instead of these functions.
.Sh BINDINGS
The
.Nm
widget provides the following bindings:
.Pp
.Bl -tag -compact -width "char *string "
.It Va char *string
Fixed-size buffer containing a "C" string (a NUL-terminated string) in the
specified encoding (UTF-8 by default).
.It Va AG_Text *text
Bound
.Xr AG_TextElement 3 ,
which can represent text in different languages.
.El
.Sh EVENTS
The
.Nm
widget generates the following events:
.Bl -tag -width 2n
.It Fn textbox-return "void"
Return was pressed and
.Dv AG_TEXTBOX_MULTILINE
is not set.
.It Fn textbox-prechg "void"
The string is about to be modified.
.It Fn textbox-postchg "void"
The string was just modified.
.El
.Sh STRUCTURE DATA
For the
.Ft AG_Textbox
object:
.Pp
.Bl -tag -compact -width "AG_Editable *ed "
.It Ft AG_Editable *ed
Pointer to the underlying
.Xr AG_Editable 3
widget.
.It Ft AG_Label *lbl
Pointer to the
.Xr AG_Label 3
(if any).
A call to
.Fn AG_TextboxSetLabel
will create a new label object.
.It Ft AG_Text *text
An initially empty
.Xr AG_TextElement 3
used as the default binding (where
.Fn AG_TextboxBind*
is not used).
.El
.Sh EXAMPLES
The following code fragment binds an
.Nm
to a fixed-size buffer (which accepts UTF-8 encoding):
.Bd -literal -offset indent
char name[32];
AG_Textbox *tb;

tb = AG_TextboxNew(parent, 0, "Name: ");
AG_TextboxBindUTF8(tb, name, sizeof(name));
.Ed
.Pp
When no specific binding is provided (as in the following case),
.Nm
uses an internal, built-in text buffer:
.Bd -literal -offset indent
AG_Textbox *tb;
char *s;

tb = AG_TextboxNew(parent, 0, "Value: ");
AG_TextboxPrintf(tb, "Foo");

/* Retrieve the string. */
s = AG_TextboxDupString(tb);
.Ed
.Pp
An
.Xr AG_TextElement 3
can accomodate a potentially large, dynamically-allocated string:
.Bd -literal -offset indent
AG_TextElement *txt;
AG_Textbox *tb;

txt = AG_TextNew(0);
tb = AG_TextboxNew(parent, AG_TEXTBOX_EXCL |
                           AG_TEXTBOX_MULTILINE, NULL);
AG_TextboxBindText(tb, txt);
.Ed
.Pp
The following code fragment sets up a simple autocomplete routine:
.Pp
.Bd -literal
static void
MyAutocomplete(AG_Event *event)
{
	const char *dict[] = { "Apple", "Orange", "Banana", NULL }, **dp;
	AG_Editable *ed = AG_EDITABLE_SELF();
	AG_Tlist *tl = AG_TLIST_PTR(1);
	char *s, *sp;

	if ((sp = s = AG_EditableDupString(ed)) == NULL) {
		return;
	}
	while (*sp == ' ')                /* Strip leading whitespace */
		sp++;

	AG_TlistBegin(tl);
	for (dp = dictFirst; *dp != NULL; dp++) {
		if (sp[0] == '\0' ||
		    AG_Strncasecmp(*dp, sp, strlen(sp)) == 0) {
			AG_TlistAddPtr(tl, NULL, *dp, (void *)*dp);
		}
	}
	AG_TlistEnd(tl);
	free(s);
}

...

AG_Textbox *tb;

tb = AG_TextboxNew(NULL, 0, "Fruit: ");
AG_TextboxAutocomplete(tb, MyAutocomplete, NULL);
.Ed
.Sh SEE ALSO
.Xr AG_Intro 3 ,
.Xr AG_Editable 3 ,
.Xr AG_Text 3 ,
.Xr AG_TextElement 3 ,
.Xr AG_Tlist 3 ,
.Xr AG_Widget 3 ,
.Xr AG_Window 3
.Sh HISTORY
An
.Nm
widget first appeared in Agar 1.0.
It was rewritten as a front-end to
.Xr AG_Editable 3
in Agar 1.3.2.
Support for dynamically-resized text buffers was added in Agar 1.4.0.
.Fn AG_TextboxAutocomplete
and
.Dv AG_TEXTBOX_RETURN_BUTTON
appeared in Agar 1.6.0.
.Dv AG_TEXTBOX_UPPERCASE
and
.Dv AG_TEXTBOX_LOWERCASE
appeared in Agar 1.6.0.
The former
.Dv AG_TEXTBOX_NOEMACS
flag was renamed
.Dv AG_TEXTBOX_NO_KILL_YANK
and
.Dv AG_TEXTBOX_NOLATIN1
was renamed
.Dv AG_TEXTBOX_NO_ALT_LATIN1
in Agar 1.6.0.
Clipboard integration,
.Fn AG_EditableAutocomplete
and
.Fn AG_EditableCatString
appeared in Agar 1.6.0.
